package org.dxy.trigger.http.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.api.dto.request.*;
import org.dxy.api.dto.response.OptionDto;
import org.dxy.api.dto.response.RouteProcessDTO;
import org.dxy.api.dto.response.R;
import org.dxy.domain.command.route.*;
import org.dxy.domain.handler.CommandHandler;
import org.dxy.infrastructure.persistent.po.query.RouteViewPo;
import org.dxy.infrastructure.persistent.po.query.RouteProcessViewPo;
import org.dxy.infrastructure.persistent.po.query.ProcessViewPo;
import org.dxy.infrastructure.persistent.service.RouteViewService;
import org.dxy.infrastructure.persistent.service.RouteProcessViewService;
import org.dxy.infrastructure.persistent.service.ProcessViewService;
import org.dxy.trigger.http.service.RouteApplicationService;
import org.dxy.types.common.CommandResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 工艺路线应用服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RouteApplicationServiceImpl implements RouteApplicationService {
    
    private final CommandHandler<CreateRouteCommand, Long> createHandler;
    private final CommandHandler<UpdateRouteCommand, Void> updateHandler;
    private final CommandHandler<RouteEnableCommand, Void> enableHandler;
    private final CommandHandler<RouteDisableCommand, Void> disableHandler;
    private final CommandHandler<RoutePublishCommand, Void> publishHandler;
    private final CommandHandler<RouteArchiveCommand, Void> archiveHandler;
    private final CommandHandler<RouteAssignProcessesCommand, Void> addStepHandler;
    private final CommandHandler<RouteRemoveStepCommand, Void> removeStepHandler;
    private final CommandHandler<RouteReorderStepCommand, Void> reorderStepsHandler;
    private final CommandHandler<RouteStepUpdateCommand, Void> updateStepHandler;
    private final CommandHandler<DeleteRouteCommand, Void> deleteHandler;
    private final CommandHandler<BatchDeleteRouteCommand, Void> batchDeleteHandler;
    private final RouteViewService routeViewService;
    private final RouteProcessViewService routeProcessViewService;
    private final ProcessViewService processViewService;

    @Transactional
    @Override
    public R<Long> create(CreateRouteRequest request) {
        try {
            CreateRouteCommand command = new CreateRouteCommand(
                    request.getRouteCode()
            );
            
            CommandResult<Long> result = createHandler.handle(command);
            
            if (result.success()) {
                // 保存基础读模型信息
                RouteViewPo routeView = RouteViewPo.builder()
                        .id(result.data())
                        .routeCode(request.getRouteCode())
                        .routeName(request.getRouteName())
                        .routeType(request.getRouteType())
                        .version(request.getVersion()) // 默认版本
                        .description(request.getDescription())
                        .build();
                
                routeViewService.save(routeView);
                
                return R.ok(result.data(), result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("创建工艺路线失败", e);
            return R.fail("创建工艺路线失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> update(Long routeId, UpdateRouteRequest request) {
        try {
            UpdateRouteCommand command = new UpdateRouteCommand(
                    routeId,
                    request.getStepIds()
            );
            
            CommandResult<Void> result = updateHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("更新工艺路线失败, routeId={}", routeId, e);
            return R.fail("更新工艺路线失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> enable(Long routeId) {
        try {
            RouteEnableCommand command = new RouteEnableCommand(routeId);
            
            CommandResult<Void> result = enableHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("启用工艺路线失败, routeId={}", routeId, e);
            return R.fail("启用工艺路线失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> disable(Long routeId) {
        try {
            RouteDisableCommand command = new RouteDisableCommand(routeId);
            
            CommandResult<Void> result = disableHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("禁用工艺路线失败, routeId={}", routeId, e);
            return R.fail("禁用工艺路线失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> publish(Long routeId) {
        try {
            RoutePublishCommand command = new RoutePublishCommand(routeId);
            
            CommandResult<Void> result = publishHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("发布工艺路线失败, routeId={}", routeId, e);
            return R.fail("发布工艺路线失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> archive(Long routeId) {
        try {
            RouteArchiveCommand command = new RouteArchiveCommand(routeId);
            
            CommandResult<Void> result = archiveHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("归档工艺路线失败, routeId={}", routeId, e);
            return R.fail("归档工艺路线失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> assignProcesses(Long routeId, RouteAssignProcessesRequest request) {
        try {
            RouteAssignProcessesCommand command = new RouteAssignProcessesCommand(
                    routeId,
                    request.getProcessIds()
            );
            
            CommandResult<Void> result = addStepHandler.handle(command);
            
            if (result.success()) {
                // 先删除该工艺路线的所有工序关系（覆盖模式）
                routeProcessViewService.removeByRouteId(routeId);
                
                // 批量保存新的工序关系
                routeProcessViewService.saveRouteProcesses(routeId, request.getProcessIds());
                
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("添加工艺路线步骤失败, routeId={}", routeId, e);
            return R.fail("添加工艺路线步骤失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> removeStep(Long routeId, RouteRemoveStepRequest request) {
        try {
            RouteRemoveStepCommand command = new RouteRemoveStepCommand(
                    routeId,
                    request.getStepId()
            );
            
            CommandResult<Void> result = removeStepHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("移除工艺路线步骤失败, routeId={}", routeId, e);
            return R.fail("移除工艺路线步骤失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> reorderSteps(Long routeId, RouteReorderStepRequest request) {
        try {
            RouteReorderStepCommand command = new RouteReorderStepCommand(
                    routeId,
                    request.getStepIds()
            );
            
            CommandResult<Void> result = reorderStepsHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("重新排序工艺路线步骤失败, routeId={}", routeId, e);
            return R.fail("重新排序工艺路线步骤失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Void> updateStep(Long routeId, RouteStepUpdateRequest request) {
        try {
            RouteStepUpdateCommand command = new RouteStepUpdateCommand(
                    routeId,
                    request.getStepId(),
                    request.getExecutorEquipmentIds(),
                    null, // collectionParams - commented out in original code
                    null  // executionStrategy - commented out in original code
            );
            
            CommandResult<Void> result = updateStepHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("更新工艺路线步骤失败, routeId={}", routeId, e);
            return R.fail("更新工艺路线步骤失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Page<RouteViewPo>> list(Page<RouteViewPo> page, RouteViewPo query) {
        try {
            // 构建查询条件
            com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<RouteViewPo> queryWrapper =
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
            
            // 根据查询条件动态构建where子句
            if (query != null) {
                // 路线编码模糊查询
                if (query.getRouteCode() != null && !query.getRouteCode().trim().isEmpty()) {
                    queryWrapper.like(RouteViewPo::getRouteCode, query.getRouteCode().trim());
                }
                
                // 路线名称模糊查询
                if (query.getRouteName() != null && !query.getRouteName().trim().isEmpty()) {
                    queryWrapper.like(RouteViewPo::getRouteName, query.getRouteName().trim());
                }
                
                // 路线状态精确查询
                if (query.getStatus() != null && !query.getStatus().trim().isEmpty()) {
                    queryWrapper.eq(RouteViewPo::getStatus, query.getStatus().trim());
                }
                
                // 路线类型精确查询
                if (query.getRouteType() != null && !query.getRouteType().trim().isEmpty()) {
                    queryWrapper.eq(RouteViewPo::getRouteType, query.getRouteType().trim());
                }
                
                // 版本号精确查询
                if (query.getVersion() != null && !query.getVersion().trim().isEmpty()) {
                    queryWrapper.eq(RouteViewPo::getVersion, query.getVersion().trim());
                }
            }
            
            // 按创建时间倒序排列
            queryWrapper.orderByDesc(RouteViewPo::getCreatedTime);
            
            // 执行分页查询
            Page<RouteViewPo> result = routeViewService.page(page, queryWrapper);
            
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询工艺路线列表失败", e);
            return R.fail("查询工艺路线列表失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<RouteViewPo> getById(Long routeId) {
        try {
            RouteViewPo route = routeViewService.getById(routeId);
            if (route != null) {
                return R.ok(route, "查询成功");
            } else {
                return R.fail("工艺路线不存在");
            }
        } catch (Exception e) {
            log.error("查询工艺路线详情失败, routeId={}", routeId, e);
            return R.fail("查询工艺路线详情失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<Page<RouteViewPo>> getByStatus(Page<RouteViewPo> page, String status) {
        try {
            // 构建查询条件
            com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<RouteViewPo> queryWrapper =
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
            
            // 按状态精确查询
            if (status != null && !status.trim().isEmpty()) {
                queryWrapper.eq(RouteViewPo::getStatus, status.trim());
            }
            
            // 按创建时间倒序排列
            queryWrapper.orderByDesc(RouteViewPo::getCreatedTime);
            
            // 执行分页查询
            Page<RouteViewPo> result = routeViewService.page(page, queryWrapper);
            
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("按状态查询工艺路线失败, status={}", status, e);
            return R.fail("按状态查询工艺路线失败: " + e.getMessage());
        }
    }
    
    @Override
    public R<List<RouteProcessDTO>> getRouteProcesses(Long routeId) {
        try {
            // 查询工艺路线的工序关系列表
            List<RouteProcessViewPo> routeProcessList = routeProcessViewService.listByRouteId(routeId);
            
            if (routeProcessList.isEmpty()) {
                return R.ok(List.of(), "该工艺路线暂无分配工序");
            }
            
            // 提取工序ID列表
            List<Long> processIds = routeProcessList.stream()
                    .map(RouteProcessViewPo::getProcessId)
                    .collect(Collectors.toList());
            
            // 批量查询工序详情
            List<ProcessViewPo> processList = processViewService.listByIds(processIds);
            
            // 转换为DTO并保持顺序
            List<RouteProcessDTO> result = routeProcessList.stream()
                    .map(routeProcess -> {
                        // 找到对应的工序详情
                        ProcessViewPo process = processList.stream()
                                .filter(p -> p.getId().equals(routeProcess.getProcessId()))
                                .findFirst()
                                .orElse(null);
                        
                        return RouteProcessDTO.builder()
                                .processId(routeProcess.getProcessId())
                                .processCode(process != null ? process.getProcessCode() : "")
                                .processName(process != null ? process.getProcessName() : "")
                                .stepOrder(routeProcess.getStepOrder())
                                .remark(routeProcess.getRemark())
                                .build();
                    })
                    .collect(Collectors.toList());
            
            return R.ok(result, "查询成功");
        } catch (Exception e) {
            log.error("查询工艺路线工序列表失败, routeId={}", routeId, e);
            return R.fail("查询工艺路线工序列表失败: " + e.getMessage());
        }
    }
    
    @Transactional
    @Override
    public R<Void> delete(Long routeId) {
        try {
            DeleteRouteCommand command = new DeleteRouteCommand(routeId);
            
            CommandResult<Void> result = deleteHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("删除工艺路线失败, routeId={}", routeId, e);
            return R.fail("删除工艺路线失败: " + e.getMessage());
        }
    }
    
    @Transactional
    @Override
    public R<Void> batchDelete(RouteBatchDeleteRequest request) {
        try {
            BatchDeleteRouteCommand command = new BatchDeleteRouteCommand(request.getIds());
            
            CommandResult<Void> result = batchDeleteHandler.handle(command);
            
            if (result.success()) {
                return R.ok(result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("批量删除工艺路线失败, routeIds={}", request.getIds(), e);
            return R.fail("批量删除工艺路线失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<OptionDto>> getRouteOptions() {
        try {
            log.info("开始查询工艺路线选项列表");
            
            // 查询启用状态的工艺路线
            List<RouteViewPo> routes = routeViewService.list(
                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<RouteViewPo>()
                    .eq(RouteViewPo::getStatus, "enable")
                    .orderByAsc(RouteViewPo::getRouteName)
            );
            
            List<OptionDto> options = routes.stream()
                    .map(route -> OptionDto.builder()
                            .id(String.valueOf(route.getId()))
                            .name(route.getRouteName())
                            .code(route.getRouteCode())
                            .description(route.getDescription())
                            .build())
                    .collect(Collectors.toList());
            
            log.info("查询工艺路线选项列表成功: count={}", options.size());
            return R.ok(options, "查询成功");
            
        } catch (Exception e) {
            log.error("查询工艺路线选项列表失败", e);
            return R.fail("查询工艺路线选项列表失败: " + e.getMessage());
        }
    }

}